#-*- coding: utf-8 -*-

#--- PYTHON IMPORTS ---
import random
import datetime

#--- FRAMEWORK IMPORTS ---
from django import forms
from django.forms.util import ErrorList
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.admin.widgets import AdminFileWidget as FileWidget
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext

#--- APP IMPORTS ---
from app_settings import *
from fields import SafeHtmlField
from . import models

# utilizado no SearchForm
sort_choices = [
    ('newest', ugettext('Newest')),
    ('older', ugettext('Older')),
    ('views', ugettext('Number of views')),
    ('reply', ugettext('Number of replies'))
]

# utilizado no SearchForm
date_choices = [
    ("1", ugettext('1 month')),
    ("6", ugettext('6 months')),
    ("12", ugettext('12 months')),
    ("all", ugettext('All times')),
]

forum_image = models.Forum._meta.get_field("image")
forum_image_small = models.Forum._meta.get_field("image_small")

class ForumForm(forms.ModelForm):
    """
    Creates a form that does not require a parent forum
    description : this form is used to create new Forun's through
        regular means
    """
    
    def clean(self):
        pt_value = self.cleaned_data['parent']
        gp_value = self.cleaned_data['group']
        
        if not any((pt_value, gp_value)):
            raise forms.ValidationError(_("Both fields, group"
                " and parent forum, can't be empty at the same time."))
        return self.cleaned_data
    
    class Meta:
        model = models.Forum
        exclude = ('slug', )


class ForumFormAdmin(ForumForm):
    class Meta(ForumForm.Meta):
        exclude = None


class ReplyForm(forms.ModelForm):
    "Regular answer form"
    
    # valid tags and attributes for content field
    text = SafeHtmlField(label=_("Text"), required=True,
            widget=forms.Textarea(attrs={'class':'span-16 mooeditable'}))

    def clean_text(self):
        data = self.cleaned_data["text"]
        if data is None or data=="":
            raise forms.ValidationError(_("Empty answers are not allowed."))
        else: return data
        
    def as_ul(self):
        return self._html_output(u'<li>%(errors)s<div class="clearfix">%(label)s <span class="quiet small">%(help_text)s</span></div> %(field)s</li>', u'<li>%s</li>', '</li>', u' %s', False)

    class Meta:
        model = models.Reply
        fields = ('title', 'text')


class ModerateForm(forms.ModelForm):
    class Meta:
        model = models.Topic
        fields = ["closed", "fixed", "active"]


class TopicForm(forms.ModelForm):
    text = SafeHtmlField(label=_('Text'), required=True,
                         widget=forms.Textarea(attrs={'class':'span-16 mooeditable'}))
    
    def clean_title(self):
        return self.cleaned_data["title"].capitalize()
    
    def clean_text(self):
        data = self.cleaned_data["text"]
        if data is None or data=="":
            raise forms.ValidationError(_("Empty answers are not allowed."))
        else: return data

    def clean_cover_picture(self):
        # make sure image filesize is not too big
        img = self.cleaned_data["cover_picture"]
        
        if img:
            if img.size > 1024*TOPIC_IMAGE_SIZE:
                raise forms.ValidationError(_("User image must have at most %d kb") % TOPIC_IMAGE_SIZE)
            return img
        return None

    def clean_attach(self):
        # if has attach, clean it ; )
        data = self.cleaned_data["attach"]
        if data is None:
            return None
        elif isinstance(data, basestring):
            return data
        else:
            import mimetypes
            if data.size > 1024*TOPIC_ATTACH_SIZE:
                raise forms.ValidationError(_("Attached file is too big. Max attach size is %d kb") % TOPIC_ATTACH_SIZE)
            if mimetypes.guess_type(data.name)[0] in TOPIC_ATTACH_FILTER:
                raise forms.ValidationError(_("The attachment type is not allowed."))
            return data
        
    class Meta:
        model = models.Topic
        fields = ('image', 'title', 'short', 'text', 'attach')

class TopicFormAdmin(TopicForm):
    class Meta(TopicForm.Meta):
        fields = None

class PollOptionForm(forms.ModelForm):
    def clean_image(self):
        max_size = 20
        img = self.cleaned_data['image']
        if img is not None:
            if img.size > 1024*max_size: # 20kb
                raise forms.ValidationError(_("Image file is too big. Max file size should be %dkb or less.") % max_size)
        return img

    class Meta:
        model = models.PollPick

class PollOptionFormAdmin(PollOptionForm): pass

class ReportAbuseForm(forms.ModelForm):
    class Meta:
        model = models.ReportAbuse
        exclude = ('topic', )

# meta data from ForumProfile
forum_profile_img = models.ForumProfile._meta.get_field("image")
forum_profile_signature = models.ForumProfile._meta.get_field("signature")

class UserProfileForm(forms.ModelForm):
    "Form for user private data"
    image = forms.ImageField(label=forum_profile_img.verbose_name, required=False,
                                help_text=forum_profile_img.help_text, widget=FileWidget())

    signature = SafeHtmlField(widget=forms.Textarea(attrs={'class':'mooeditable span-16'}), required=False,
                              label=forum_profile_signature.verbose_name,
                              help_text=forum_profile_signature.help_text)
    
    def clean_signature(self):
        sig = self.cleaned_data['signature']
        if sig is None: return sig
        else:
            if len(sig)>600:
                raise forms.ValidationError(_('Signature must have up to 600 characters'))
            else: return sig

    def clean_image(self):
        img = self.cleaned_data["image"]
        if img is None or isinstance(img, basestring):
            return img

        if img.size > 1024*AVATAR_MAX_SIZE:
            raise forms.ValidationError(_("The user image must have, at most, %(max_size)dkb") % {"max_size":AVATAR_MAX_SIZE})

        from PIL import Image
        from StringIO import StringIO

        image = Image.open(StringIO(img.read()))
        width, height = image.size

        if (width > AVATAR_MAX_WIDTH) or (height > AVATAR_MAX_HEIGHT):
            raise forms.ValidationError(_("User image's size must have %(width)d x %(height)d pixels at most") % {"width":AVATAR_MAX_WIDTH, "height":AVATAR_MAX_HEIGHT})
        return img

    class Meta:
        model = models.ForumProfile
        fields = ('pvt_only_from_friends', 'image', 'signature')

forum_choice_query = models.Forum.objects.all()

class SearchForm(forms.Form):
    keyword = forms.CharField(label=_("Having keywords..."), max_length=60, required=False)
    author = forms.ModelChoiceField(queryset=models.User.objects.all(), label=_("Filter by user..."), required=False)
    date = forms.ChoiceField(date_choices, initial='all',
        label=_("Results from up to"))
    sort_method = forms.ChoiceField(sort_choices, 
        label=_("Sort results by..."), initial=sort_choices[0][0], required=True)
    forum = forms.ModelChoiceField(forum_choice_query, 
        label=_("Search only in Forum..."), required=False)
        
    def _query_string(self):
        return to_query_string(self.cleaned_data)    
        
    def clean_author(self):
        return self.cleaned_data.get("author", None)
    
    def clean_date(self):
        data = self.cleaned_data.get("date", None)        
        if data == 'all': return None
        else: return int(data)

    def get_query(self):
        date = self.cleaned_data["date"]
        keyword = self.cleaned_data["keyword"]
        author = self.cleaned_data["author"]
        sort_method = self.cleaned_data["sort_method"]
        forum = self.cleaned_data["forum"]

        # todos os filtros sao aplicados nesta query
        query = models.Topic.objects.active()
        
        if keyword: # jogada contra o titulo dos topicos
            query = query.filter(title__icontains=keyword)
        if author:
            query = query.filter(author=author)
        if date is not None:
            up_to_date = datetime.datetime.now() - datetime.timedelta(weeks=4*date)
            query = query.filter(created_time__gt=up_to_date)
        if forum is not None:
            query = query.filter(forum=forum)        
        if sort_method is not None:
            if sort_method=="newest":
                query = query.order_by("-created_time")
            elif sort_method=="older":
                query = query.order_by("created_time")
            elif sort_method=="views":
                query = query.order_by("-views_count")
            elif sort_method=="reply":
                query = query.order_by("-reply_count")
        return query
    
    # alias
    query_string = property(_query_string)
    query = property(get_query)

pvt_title = models.ForumMessage._meta.get_field("title")
class SendPvtForm(forms.Form):
    "Private message form"
    title = forms.CharField(label=_("Message Title"),
        max_length=pvt_title.max_length)
    message = SafeHtmlField(label=_("Message"),
        widget=forms.Textarea(attrs={'class':'mooeditable span-16'}))

    def as_ul(self):
        return self._html_output(u'<li>%(errors)s<div class="clearfix">%(label)s <span class="quiet small">%(help_text)s</span></div> %(field)s</li>', u'<li>%s</li>', '</li>', u' %s', False)

    def save(self, author, msg_box, commit=True):
        if msg_box.is_full():
            return None, 'full'
        
        title = self.cleaned_data['title']
        content = self.cleaned_data['message']

        frm_message = models.ForumMessage(title=title, content=content,
            author=author.username, box=msg_box)
        
        if commit:
            frm_message.save()
        return frm_message, 'ok'

def to_query_string(dict, filter=[]):
    return '&'.join(["%s=%s" % (key, dict[key]) for key in dict.keys() if dict[key] not in (None, '')])
    
